home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Diamond Collection
/
The Diamond Collection (Software Vault)(Digital Impact).ISO
/
cdr48
/
386p_200.zip
/
386VIDEO.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-01-12
|
33KB
|
1,026 lines
; ESSENTIAL VIDEO SERVICES plus
; the default MCGA/VGA XVD driver
;
; WARNING! The current 386video mode supports ONLY 320x200 graphics modes
; with scanline=320 and screen buffer as wide as you can fit it into ram.
;
; If you want higher screen resolutions you will have to
; modify the 386video management routines
; (the XVD video drivers DO SUPPORT higher screen resolutions
; and "linear aperture" mapping, but the current the 386video module does not
; use these capabilities).
;
; The reason of this is that i'm working on a 320x200 thing
; and don't have enough time to work on a "full power" 386video
; with slower mode 320x200 functions (you know, keeping track of
; video pages boundaries adds cpu overhead)
;
; If you want to support higher resolutions just update the 386video
; mode initialization,touchmapping and pageflipping routines.
; Look into genflip0.asm to have an idea how >64k pageflipping works.
; If you want to see how to code an XVD "external" driver look into
; the chip450.asm source file
; N.B. video page = a 64k block of video memory
; display buffer = a sequence of video pages describing the current
; image being displayed (it is located into video ram)
; screen buffer = big bitmap CONTAINING a COPY of the display buffer
; (usually you set the screen buffer bigger than the
; display buffer to support "sprites getting in/out
; of the screen border" by simply blitting them
; on the bigger screen buffer and then copying
; only the "visible" portion of it to display buffer)
; usually located in RAM
.386P
code32 segment para public use32
assume cs:code32,ds:code32
include 386power.inc
include 386file.inc
include 386sys.inc
include headxvd.inc
public _ScrBase,_RowStart
align dword
MAXLINES = 1024
; index of row start offsets from base of display screen
; maximum vertical resolution is 1024 lines
_RowStart dd 0
dd MAXLINES dup(0)
; Disp values are for the DISPlayed window
; Scr values are for the display page buffer
public _DispX,_DispY,_ScrX,_ScrY,_VDispX,_VDispY,_XSquare,_YSquare
public _XVDTotRam,_XVDVModes
; here starts the XVD driver data table
; every XVD driver uses to get/pass information to
; the 386video module
_XVDTable dd 0 ; card subtype id
_XVDCMode dd 0 ; last video mode you tried to set
_XVDVPages dd 1 ; available 64k units in current mode
_XVDVModes dd 011b ; support for textmode 80x25 and 320x200
_XVDScanline dd 320 ; lenght in bytes of a display scanline
_XVDAperture dd 0 ; aperture base address
_XVDASize dd 0 ; aperture region size (0 = no aperture)
_XSquare dd 32 ; _XSquare/_YSquare = pixel aspect ratio
_YSquare dd 24 ; (set by driver init code)
_XVDTotRam dd 1 ; total ram on video board in 64k units
_DispX dd 0 ; Display X resolution
_DispY dd 0 ; " Y "
; end of XVD driver table
_ScrX dd 0 ; Screen buffer X resolution
; X range = 0...(_ScrX-1)
_ScrY dd 0 ; Screen buffer Y resolution
; Y range = 0...(_ScrY-1)
_VDispX dd 0 ; Visible Display Window X coord inside screen buffer
_VDispY dd 0 ; Visible Display Window Y coord inside screen buffer
; (_VDispX,_VDispY) = upper left pixel to show
ODispX dd 0 ; previous values for VDispX,VDispY
ODispY dd 0 ;
SCRSIZE dd 0
public _ScrSD
_ScrSD dd 0 ;screen size in dwords (useful to some routines)
DSKID dd 0
XWID = 320
YHEI = 200
CHUNKSIZE dd 1
;top position where a display buffer can start
CHUNKTOP dd 1
; start position of current display buffer
THISCHUNK dd 0
_ScrBase dd 0 ;base of buffered display page
; (changed at every _PageFlip0 if multiple display pages on)
VScrBase dd 0 ;base of visible window
ViewBase dd 0 ;base of viewable display page
; (changed at every _PageFlip0 if multiple display pages on)
Physbase dd 0 ;display buffer address
; (used only to store "linear aperture" position)
_XVDBase dd 0 ;"external" driver base address
align dword
; the three palette functions are hooked directly to their XGE entry points
; the other are called indirectly
_XVDBiosCheck dd offset CheckXVD ; returns carry clear if video bios is present
_XVDChipSetCheck dd offset CheckXVD ; returns carry clear is chipset is present
; Currently both of these must be successful
; to "get access" to the graphics extensions.
; A future XGE release will try to use VESA functions
; to set the video mode if _XXVDBiosCheck fails
; and then if _XVDChipSetCheck is successful
; it will "unlock" the extensions thtu direct chipset access.
;
; To use "extended" multi-page mode 13h you only have
; to check for the chipset (the bios entry is the same
; for all boards)
;
_XVDMode dd offset XVDMode
; Set video mode , called by _SetXVDMode
; eax=requested video mode
; edi=driver table, ebp= driver base
_XVDPage dd offset XVDPage
; changes accessible video block
; in: eax= video block to access
; out: edi=linear address of block start
_XVDVisible dd offset XVDVisible
; set new visible display buffer staring block
; eax = video block
_XVDOpen dd offset unSupported
_XVDClose dd offset unSupported
_XVDLineSize dd offset unSupported
_XVDCardType dd xcardtype
_XVDProgrammer dd xprogr
_XVDNotes dd xnotes
easav dd 0 ; eax buffer for faster operations
align byte
_XVDExternal db 0 ; tried to load external driver
_XVDGoodDriver db 0 ; found XVD marker at start of driver
_XVDBGood db 0 ; check for bios OK
_XVDCGood db 0 ; check for chipset OK
public _XVDExternal,_XVDGoodDriver,_XVDBGood,_XVDCGood
xcardtype db 'VGA/MCGA COMPATIBLE',0
xprogr db 'Lorenzo Micheletto',0
xnotes db 'Default XVD driver',0
modefailure:
popad
unSupported:
stc
XVDVisible:
ret
XVDPage: mov edi,0A0000h
ret
XVDMode: pushad
mov V86ax,0003h ; text mode
mov _XVDCMode,0
or eax,eax
jz vid_mode
dec eax
jne modefailure
mov V86ax,0013h ; set graphic mode
mov _XVDCMode,1
vid_mode:
mov al,10h
call _ExecINT
popad
CheckXVD:
clc
ret
;-----------------------------------------------------------------------------
STATUS = 03DAh ; status register port
IS_HVSYNC = 01
IS_VSYNC = 08
; palette ports
DACREAD = 03C7h
DACWRITE = 03C8h
DACDATA = 03C9h
;----------------------------------------------------------------------------
; _Set1Palette al = palette entry
; edx = bit 0..7 red
; bit 8..15 green
; bit 16..23 blue
; bit 24..31 non utilizzati
;
public _Set1Pal
_Set1Pal dd offset XVDSet1Pal
XVDSet1Pal:
; al = palette index
; edx = (XBGR)
push eax
push ebx
mov ebx,edx
push edx
shr ebx,2 ; cut out lower bits to get VGA resolution
mov dx,DACWRITE
and ebx,003F3F3Fh ; eliminate garbage bits
cli
out dx,al ; index
inc dx
mov al,bl
out dx,al ; Red
mov al,bh
shr ebx,16
out dx,al ; Green
mov al,bl
out dx,al ; Blue
sti
pop edx
pop ebx
pop eax
ret
public _Get1Pal
_Get1Pal dd offset XVDGet1Pal
XVDGet1Pal:
; al = palette index
; edx = (XBGR)
push eax
; i choosed to use a BIOS call after some problems
; with my video card
mov V86bl,al
xor edx,edx
mov V86ax,1015h
mov al,10h
call _ExecINT
mov dl,V86cl
shl edx,16
mov dh,V86ch
mov dl,V86dh
shl edx,2
pop eax
ret
public _Set256Pal
_Set256Pal dd offset XVDSet256Pal
XVDSet256Pal:
; esi = pointer to 256 palette entries
; every entry is a dword (XRGB)
pushad
mov ecx,256
mov dx,STATUS
cli
into_vretrace:
in al,dx
test al,IS_VSYNC
jnz into_vretrace
outof_vretrace:
in al,dx
test al,IS_VSYNC
jz outof_vretrace
; now a full vretrace interval is available
mov dx,DACWRITE
xor eax,eax
out dx,al
inc dx ; move to DACDATA port
nextp:
mov eax,[esi]
shr eax,2 ; 8bit to 6bit color values
add esi,4
and eax,003F3F3Fh ;
out dx,al ; Red
mov al,ah
out dx,al ; Green
shr eax,16
out dx,al ; Blue
dec ecx
jne nextp
sti
popad
ret
;----------------------------------------------------------------------------
public _SetXVDMode
_SetXVDMode dd offset SetXVDMode
xname db 'XVD.XVD',0
mem_no db 'Not enough memory for XVD driver data',CR,LF,'$'
no_mem:
mov _386Return, offset mem_no
jmp _Exit
scr_noo db 'XVD driver: Cannot initialize required video mode',CR,LF,'$'
scr_no_good:
mov _386Return,offset scr_noo
jmp _Exit
xy_no db 'Wrong screen size, XVD driver does not support it',CR,LF,'$'
xy_no_good:
mov _386Return, offset xy_no
jmp _Exit
xunload: mov _HiMemBase,ebp ; restore previous himembase
mov _XVDBase,0
jmp driverloaded
SetXVDMode: ; _ScrX,_ScrY,_DispX,_DispY
; must be set before calling this
pushad
cmp _XVDBase,0 ; if already loaded an external driver
jne driverloaded ; then skip this
mov esi,offset xname ; try to load XVD.XVD
call _FLoad ;
jc driverloaded ; if cannot load driver, use default driver
mov _XVDExternal,1 ; loaded an external driver
mov ebp,_HiMemBase ; base of loaded file
cmp byte ptr [ebp],'X' ;
jne driverloaded ;
cmp byte ptr [ebp+1],'V' ;
jne driverloaded ;
cmp byte ptr [ebp+2],'D' ;
jne driverloaded ;
cmp byte ptr [ebp+3],'0' ;
jne driverloaded ; check 'XVD0' marker
mov _XVDGoodDriver,1 ; driver header looks good
mov _XVDBase,ebp
add eax,ebp
mov _HiMemBase,eax
; check if driver matches the graphics card
mov edi,offset _XVDTable
mov edx,[ebp+__XVDBiosCheck]
add edx,ebp
call edx ; check bios
jc xunload
mov _XVDBGood,1 ; bios check looks good
mov edx,[ebp+__XVDChipSetCheck]
add edx,ebp
call edx ; check chipset
jc xunload
mov _XVDCGood,1 ; chipset check looks good
; Now LINK all entries to their pointers
; correcting the driver based offsets to code32 base
mov edx,[ebp+__XVDBiosCheck]
add edx,ebp
mov _XVDBiosCheck,edx
mov edx,[ebp+__XVDChipSetCheck]
add edx,ebp
mov _XVDChipSetCheck,edx
mov edx,[ebp+__XVDMode]
add edx,ebp
mov _XVDMode,edx
mov edx,[ebp+__XVDPage]
add edx,ebp
mov _XVDPage,edx
mov edx,[ebp+__XVDVisible]
add edx,ebp
mov _XVDVisible,edx
mov edx,[ebp+__XVDOpen]
add edx,ebp
mov _XVDOpen,edx
mov edx,[ebp+__XVDClose]
add edx,ebp
mov _XVDClose,edx
mov edx,[ebp+__XVDLineSize]
add edx,ebp
mov _XVDLineSize,edx
mov edx,[ebp+__XVDSet1Pal]
add edx,ebp
mov _Set1Pal,edx
mov edx,[ebp+__XVDSet256Pal]
add edx,ebp
mov _Set256Pal,edx
mov edx,[ebp+__XVDGet1Pal]
add edx,ebp
mov _Get1Pal,edx
mov edx,[ebp+__XVDCardType]
add edx,ebp
mov _XVDCardType,edx
mov edx,[ebp+__XVDProgrammer]
add edx,ebp
mov _XVDProgrammer,edx
mov edx,[ebp+__XVDNotes]
add edx,ebp
mov _XVDNotes,edx
driverloaded:
; well, driver is initialized, now we will try
; to set up the required video mode
mov eax,_ScrX
add eax,3
and eax,0FFFFFFFCh ; round to dword count
mov _ScrX,eax
mov edx,_ScrY
mov ecx,_DispX
cmp ecx,XWID
jne xy_no_good
cmp _DispY,YHEI
jne xy_no_good
sub eax,ecx
mov DSKID,eax ; store width difference
add eax,ecx ; eax= _ScrX
mul edx ; edx= _ScrY
; eax = screen buffer size in bytes
mov ecx,eax
shr ecx,2
mov SCRSIZE,eax
mov _ScrSD,ecx ;screen buffer size in dwords
call _GetHiMem
jc no_mem
mov _ScrBase,eax
mov VScrBase,eax
xor eax,eax
mov _VDispX,eax
mov _VDispY,eax
mov edi,offset _RowStart ; Row offset table
mov ecx,_ScrY ;
mov ebx,_ScrX ;
iloop:
stosd
add eax,ebx
dec ecx
jne iloop
mov eax,1 ; try to set 320x200 video mode
mov CHUNKSIZE,1 ; set screen chunk size
mov edi,offset _XVDTable
mov ebp,_XVDBase
call _XVDMode ; set display mode
jc scr_no_good
cmp _XVDBase,0 ; if using the integrated driver
je donexvdrelink ; then skip this
; Now LINK AGAIN all entries to their pointers
; This allows the mode-initialization routine
; to change the values into the XVD device table
; (for example, changing the available video page count
; if there are bank limits you cannot "run around")
; AND to "select" mode specific routines
; depending of the video-card/graphic-mode combination
mov edx,[ebp+__XVDBiosCheck]
add edx,ebp
mov _XVDBiosCheck,edx
mov edx,[ebp+__XVDChipSetCheck]
add edx,ebp
mov _XVDChipSetCheck,edx
mov edx,[ebp+__XVDMode]
add edx,ebp
mov _XVDMode,edx
mov edx,[ebp+__XVDPage]
add edx,ebp
mov _XVDPage,edx
mov edx,[ebp+__XVDVisible]
add edx,ebp
mov _XVDVisible,edx
mov edx,[ebp+__XVDOpen]
add edx,ebp
mov _XVDOpen,edx
mov edx,[ebp+__XVDClose]
add edx,ebp
mov _XVDClose,edx
mov edx,[ebp+__XVDLineSize]
add edx,ebp
mov _XVDLineSize,edx
mov edx,[ebp+__XVDSet1Pal]
add edx,ebp
mov _Set1Pal,edx
mov edx,[ebp+__XVDSet256Pal]
add edx,ebp
mov _Set256Pal,edx
mov edx,[ebp+__XVDGet1Pal]
add edx,ebp
mov _Get1Pal,edx
mov edx,[ebp+__XVDCardType]
add edx,ebp
mov _XVDCardType,edx
mov edx,[ebp+__XVDProgrammer]
add edx,ebp
mov _XVDProgrammer,edx
mov edx,[ebp+__XVDNotes]
add edx,ebp
mov _XVDNotes,edx
; end of "re-linking"
; now see how much memory is available
; and set the "page switching" limits
donexvdrelink:
mov eax,_XVDVPages
goodbank:
sub eax,CHUNKSIZE
mov CHUNKTOP,eax
xor eax,eax ;
mov THISCHUNK,eax ; display buffer base in 64k vram pages
call _XVDPage
sub edi,_Code32Base ; store base page frame address
mov ViewBase,edi ;
; ritorna a chi ha chiamato
call MakeTouchBlitter ; initialize pageflip things
call MakeTouchMap
; insert the "video mode termination code"
mov eax, offset RestoreTextMode
call _OnExit
popad
ret
;----------------------------------------------------------------------------
; void RestoreTextMode( void )
public _RestoreTextMode
_RestoreTextMode dd offset RestoreTextMode
RestoreTextMode:
pushad
xor eax,eax
call _XVDMode
popad
ret
;----------------------------------------------------------------------------
; void DisplayStart(eax= x,edx =y) SET DISPLAY VIDEO WINDOW POSITION
; INSIDE DISPLAY PAGE
public _DisplayStart
_DisplayStart dd offset DisplayStart
DisplayStart:
; eax= x_position , edx = y_position
push eax
mov _VDispX,eax
mov _VDispY,edx
add eax,_ScrBase
add eax,[edx*4+_RowStart]
mov VScrBase,eax
pop eax
ret
; SMART PAGE FLIPPING CODE
align dword
TOUCHDSIZE = (3*YHEI)
; touchmap pointers
touch0 dd 0
touch1 dd 0
align byte
touchfrag db '386Video: TouchMap allocation failed',CR,LF,'$'
tmapfail: mov _386Return,offset touchfrag
jmp _Exit
MakeTouchMap:
mov eax,((TOUCHDSIZE*2)*4)
mov ebp,TOUCHDSIZE
call _GetHiMem
jc tmapfail
mov touch0,eax
lea ecx,[ebp*2]
mov edi,eax
lea esi,[eax+ebp*4]
xor eax,eax
mov touch1,esi
rep stosd
ret
public _TouchBlock
_TouchBlock dd offset TouchBlock
TouchBlock:
; eax,edx = xstart (dots), ystart(dots) upper-left position of block
; ecx,ebx = xwidth (nudgets), yheight (dots) of touched block in pixels
;
; N.B. This routine is currently LIMITED TO 320x200 SCREEN RESOLUTION
;
; HOW TO INTERLEAVE INSTRUCTIONS QUICKLY AND GET FASTER CODE:
; a) select TWO indipendent operations to perform
; b) subdivide the available registers between the two operations
; c) write the code for the two operations
; d) INTERLEAVE the instructions composing the two code sequences
; avoiding to "couple together" complex instructions
; BUT KEEP IN SEQUENCE instructions that depends
; from flag status result of previous instruction
; e) See the MIPS rating skyrocket when you run the resulting code
; on a 486 or Pentium processor :).
; f) Laugh when you think at what happens when somebody tries to
; perform reverse engineering on your interleaved code.
; some things are hard to interleave
pushad
; other "sequences" can be interleaved pretty quickly
; ( identation is used to show the two code sequences)
; CALCULATE BLOCK MASKS
; ecx,eax,edi
; CALCULATE STARTING POSITION OF POINTERS
; edx,ebp,esi
mov esi,eax ; GLUE CODE copy xstart in dots
inc ecx ; one more dword to round off
shr eax,2 ; dword granularity for start position
mov ebp,edx ; GLUE CODE copy yheight
add ecx,eax ; last blit position in dwords
shr esi,7 ; dword granularity , 32 dword bits onto touchlist item
; == column dword index into touchmap == xstart
; now calc ystart* 12 to get line offset
mov edi,eax ; start column in dwords
add ebp,esi ; wow! ultra-smart optimization!
; ebp & esi needs to be multiplied by 4 so ...
shl edx,3 ; ystart*8
and eax,01Fh ; mask low start count
shr edi,5 ; shift high start count
lea esi,[edx+ebp*4] ; ystart*8+((xstart/128)+ystart)*4
; = (xstart/128)*4 + ystart*12
; = offset of first dword to touch
; EBP discarded from here
mov ebp,ecx ; end column in dwords
add esi,touch0 ; START IN DWORDS base+xstart+ystart*12
; now interleave the final masking calculations
and ecx,01Fh ; mask low stop count
mov edx,-1
shl edx,cl
mov ecx,eax ; set new shift counter
shr ebp,5 ; shift high stop count
not edx ; invert bits ---> TAIL MASK
mov eax,-1
sub ebp,edi ; WIDTH IN PACKDWORDS
shl eax,cl ; HEAD MASK
mov edi,12
dec ebp ; how many PackDwords ?
jz sidebyside
jns middlestrip
; overlapping
and eax,edx
overblit:
or [esi],eax
add esi,edi
dec ebx
je eoverblit
or [esi],eax
add esi,edi
dec ebx
jne overblit
eoverblit:
popad
ret
sidebyside:
or [esi],eax
or [esi+4],edx
add esi,edi
dec ebx
je esidebyside
or [esi],eax
or [esi+4],edx
add esi,edi
dec ebx
jne sidebyside
esidebyside:
popad
ret
middlestrip:
or [esi],eax
mov dword ptr [esi+4],-1
or [esi+8],edx
add esi,edi
dec ebx
je emiddlestrip
or [esi],eax
mov dword ptr [esi+4],-1
or [esi+8],edx
add esi,edi
dec ebx
jne middlestrip
emiddlestrip:
popad
ret
;--------------------------------------------------------------------------
; void cdecl PageFlip(void)
;
public _PageFlip0
_PageFlip0 dd offset PageFlip0
PageFlip0: ; ViewBase <-- _ScrBase "brute force"
; optimized routine for 320x200 screen resolution
pushad
rawblit:
mov ebp,DSKID
mov esi,VScrBase
mov eax,THISCHUNK
mov ebx,(XWID/4) ; line width in dwords
add eax,CHUNKSIZE
cmp eax,CHUNKTOP
jb fchunkgood
xor eax,eax
fchunkgood:
mov THISCHUNK,eax
call _XVDPage
sub edi,_Code32Base
mov edx,YHEI
mov ViewBase,edi
fnextruw:
mov ecx,ebx
rep movsd
add esi,ebp
dec edx
je fruwend
; unroll one step
mov ecx,ebx
rep movsd
add esi,ebp
dec edx
jne fnextruw
fruwend:
mov eax,THISCHUNK ; set this as the next visible page
call _XVDVisible ;
jmp zapatron
public _PageFlip1
_PageFlip1 dd offset PageFlip1
PageFlip1:
; ViewBase <-- _ScrBase using TouchMaps
pushad
mov ecx,_VDispX ; test if touchmap are not effective
mov eax,_VDispY ; because of massive screen motion
cmp ecx,ODispX ;
jne rawblit ;
cmp eax,ODispY ;
jne rawblit ;
; now execute a page update without changing the visible screen
mov ebx,touch0 ; delta pages
mov ebp,touch1 ;
mov esi,VScrBase
mov edi,ViewBase
blitsome: mov ecx,YHEI
xor eax,eax
blitdline:
; blit first 128 dots
mov edx,[ebx]
or edx,[ebp]
mov al,dl
call [eax*4+touchdown]
mov al,dh
shr edx,16
call [eax*4+touchdown]
mov al,dl
shr edx,8
call [eax*4+touchdown]
call [edx*4+touchdown]
; blit other 128 dots
mov edx,[ebx+4]
or edx,[ebp+4]
mov al,dl
call [eax*4+touchdown]
mov al,dh
shr edx,16
call [eax*4+touchdown]
mov al,dl
shr edx,8
call [eax*4+touchdown]
call [edx*4+touchdown]
; blit the last 64 dots
mov edx,[ebx+8]
or edx,[ebp+8]
mov al,dl
call [eax*4+touchdown]
mov al,dh
add ebx,12
add ebp,12
call [eax*4+touchdown]
add esi,DSKID
dec ecx
jne blitdline
zapatron:
; update touchmap pointers & reset current touchmap
mov ebx,touch0 ; switch delta pages
mov edi,touch1 ;
mov touch0,edi ;
mov touch1,ebx ;
xor eax,eax
mov ecx,TOUCHDSIZE
rep stosd
; update old screen pos
mov edx,_VDispX
mov eax,_VDispY
mov ODispX,edx
mov ODispY,eax
popad
ret
; END OF PAGE FLIPPING CODE
; list of pointer to optimized code blitting snippets
touchdown dd 256 dup(0)
WADDESIB = 0C683h
WADDEDIB = 0C783h
BMOVSD = 0A5h
BRETN = 0C3h
nocomp db ' Not enough High Memory for BLIT COMPILER ',CR,LF,'$'
bombed:
mov _386Return,offset nocomp
jmp _Exit
; initializes the touchdown list
; "compiling" the chunk blit code
MakeTouchBlitter:
pushad
mov edi,_HiMemBase ; use high memory
mov esi,_HiMemTop ;
sub esi,edi ; available space
mov ebx,offset touchdown ; pointer to touch blitter table
xor ecx,ecx ; ecx=0 chunk counter
inflate:
xor edx,edx ; edx=0 skip counter
mov [ebx],edi ; store start of this blit code chunk
mov ebp,8 ; 8 touchbits to evaluate
add ebx,4 ; next item
mov eax,ecx
inflatebyte:
shr eax,1
jc blast
add edx,4 ; increase skip if don't-touch
inflagain:
dec ebp
jnz inflatebyte
test edx,edx
jz notail
sub esi,6
jb bombed
mov word ptr [edi],WADDESIB
mov [edi+2],dl
mov word ptr [edi+3],WADDEDIB
mov [edi+5],dl
add edi,6
notail:
sub esi,1
js bombed
mov byte ptr [edi],BRETN
inc edi
inc cl
jnz inflate
mov _HiMemBase,edi
popad
ret
blast:
test edx,edx
jz noskippy
sub esi,6
jb bombed
mov word ptr [edi],WADDESIB
mov [edi+2],dl
mov word ptr [edi+3],WADDEDIB
mov [edi+5],dl
add edi,6
noskippy:
sub esi,1
js bombed
mov byte ptr [edi],BMOVSD
inc edi
xor edx,edx
jmp short inflagain
public _CompFlip
_CompFlip dd offset CompFlip
CompFlip:
; Compiles a pageflipping mask or a pageflipping routine
; (useful when the portions you have to "refresh" are nearly always
; the same)
; to do this you have to pass the base and top pointers
; to the heap you want to store the pageflip data on.
; BEFORE:
; Use _TouchBlock to set the current touchmap as you want
; the "compiled pageflipper" will act.
; IN:
; eax = allocation heap base , edx = allocation heap top
; OUT:
; IF CARRY CLEAR THEN
; eax = NEW allocation heap base, edx = NEW allocation heap top
; edi = pointer to custom pageflipping data/code
; ELSE NOT ENOUGH MEMORY, NOTHING HAPPENED
push edx
sub edx,eax
cmp edx,TOUCHDSIZE
jb outofmem
push ecx
push esi
mov edi,eax
mov esi,touch0
mov ecx,TOUCHDSIZE
rep movsd
pop esi
pop ecx
pop edx
xchg edi,eax
clc
ret
outofmem:
pop edx
stc
ret
extrn _CustomFlip:dword
; Executes a custom pageflipping as compiled from _CompFlip
; but doesn't updates the touchmaps
; (it is supposed you don't use touchmaps if you want a custom flip)
; IN:
; eax= pointer to custom pageflipping data/code
pushad
mov ebx,eax
mov esi,VScrBase
mov edi,ViewBase
mov ecx,_DispY
xor eax,eax
cblitdline:
; blit first 128 dots
mov edx,[ebx]
mov al,dl
call [eax*4+touchdown]
mov al,dh
shr edx,16
call [eax*4+touchdown]
mov al,dl
shr edx,8
call [eax*4+touchdown]
call [edx*4+touchdown]
; blit other 128 dots
mov edx,[ebx+4]
mov al,dl
call [eax*4+touchdown]
mov al,dh
shr edx,16
call [eax*4+touchdown]
mov al,dl
shr edx,8
call [eax*4+touchdown]
call [edx*4+touchdown]
; blit the last 64 dots
mov edx,[ebx+8]
mov al,dl
call [eax*4+touchdown]
mov al,dh
add ebx,12
add ebp,12
call [eax*4+touchdown]
add esi,DSKID
dec ecx
jne cblitdline
; update old screen pos
mov edx,_VDispX
mov eax,_VDispY
mov ODispX,edx
mov ODispY,eax
popad
ret
code32 ends
END